package com.skyline.courier.net.provider.netty;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.compression.JZlibDecoder;
import io.netty.handler.codec.compression.JZlibEncoder;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.timeout.IdleStateHandler;

import com.skyline.common.utils.ClassLoaderUtils;
import com.skyline.courier.net.ConnectionManager;
import com.skyline.courier.net.Serializer;
import com.skyline.courier.net.Statistic;

public class NettyEndPointInitializer extends ChannelInitializer<SocketChannel> {
	protected Serializer serializer;
	protected Integer writeIdleTime;
	protected Integer readIdleTime;
	protected Statistic statistic;
	protected ConnectionManager connectionManager;

	public void setSerializer(Serializer serializer) {
		this.serializer = serializer;
	}

	public void setReadIdleTime(Integer readIdleTime) {
		this.readIdleTime = readIdleTime;
	}

	public void setWriteIdleTime(Integer writeIdleTime) {
		this.writeIdleTime = writeIdleTime;
	}

	public void setStatistic(Statistic statistic) {
		this.statistic = statistic;
	}

	@Override
	protected void initChannel(SocketChannel ch) throws Exception {
		ChannelPipeline pipeline = ch.pipeline();

		pipeline.addLast("compress", new JZlibEncoder());
		pipeline.addLast("encode", new ObjectEncoder());
		pipeline.addLast("serialize", new NettySerializeHandler(serializer));

		pipeline.addLast("decompress", new JZlibDecoder());
		pipeline.addLast(
				"decode",
				new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.weakCachingResolver(ClassLoaderUtils
						.getClassLoader())));
		pipeline.addLast("deserialize", new NettyDeserializeHandler(serializer));

		pipeline.addLast("timeout", new IdleStateHandler(readIdleTime, writeIdleTime, 0));
		pipeline.addLast("statemanager", new StateManagerChannelHandler(statistic, connectionManager));
	}
}
